package org.dlow.annotation;

import org.dlow.common.constants.FaultTolerant;
import org.dlow.common.constants.LoadBalance;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.util.concurrent.TimeUnit;

/**
 * @RpcReference - RPC服务引用注解(客户端使用)
 * 
 * <p>该注解用于在客户端标记需要远程调用的服务接口,替代Spring的@Autowired注解。
 * 框架会自动为标记了此注解的字段生成代理对象,实现透明的远程服务调用。
 * 
 * <h3>核心功能:</h3>
 * <ul>
 *   <li>自动生成服务接口的代理对象</li>
 *   <li>自动订阅服务(从注册中心获取服务提供者列表)</li>
 *   <li>支持配置负载均衡策略、容错策略、超时时间等</li>
 * </ul>
 * 
 * <h3>使用示例:</h3>
 * <pre>
 * &#64;RestController
 * public class UserController {
 *     
 *     // 最简单的使用方式,使用默认配置
 *     &#64;RpcReference
 *     private UserService userService;
 *     
 *     // 指定版本号和负载均衡策略
 *     &#64;RpcReference(version = "2.0", loadBalance = LoadBalance.Random)
 *     private OrderService orderService;
 *     
 *     // 配置超时时间和容错策略
 *     &#64;RpcReference(
 *         time = 5000,
 *         timeUnit = TimeUnit.MILLISECONDS,
 *         faultTolerant = FaultTolerant.Failfast
 *     )
 *     private PaymentService paymentService;
 *     
 *     &#64;GetMapping("/user/{id}")
 *     public User getUser(Long id) {
 *         // 像调用本地方法一样调用远程服务
 *         return userService.getUserById(id);
 *     }
 * }
 * </pre>
 * 
 * <h3>工作原理:</h3>
 * <ol>
 *   <li>ConsumerPostProcessor后置处理器扫描所有Bean的字段</li>
 *   <li>发现标记了@RpcReference的字段</li>
 *   <li>使用代理工厂(如CGLib)为该接口生成代理对象</li>
 *   <li>从注册中心订阅该服务,获取提供者列表</li>
 *   <li>将代理对象注入到字段中</li>
 *   <li>后续调用该字段的方法时,实际执行的是代理对象的远程调用逻辑</li>
 * </ol>
 * 
 * <h3>注意事项:</h3>
 * <ul>
 *   <li>此注解只能用于接口类型的字段,不能用于实现类</li>
 *   <li>version需要与服务端的@RpcService版本号一致</li>
 *   <li>负载均衡策略从枚举改为字符串形式,更加灵活(参考LoadBalance枚举作为文档)</li>
 * </ul>
 * 
 * @description: 客户端服务引用注解,自动生成代理对象并订阅服务
 * @Author: 山沐与山
 * @CreateTime: 2024-05-17 00:25
 * @see ConsumerPostProcessor 处理此注解的后置处理器
 * @see org.dlow.proxy.ServiceProxyProvider 代理对象生成器
 */
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.FIELD,ElementType.TYPE})
public @interface RpcReference {

    /**
     * 服务版本号
     * <p>用于区分同一个服务接口的不同版本实现。
     * 客户端的version必须与服务端@RpcService的version一致才能正确调用。
     * 
     * @return 版本号,默认为"1.0"
     */
    String version() default "1.0";

    /**
     * 容错策略
     * <p>当远程调用失败时的处理策略:
     * <ul>
     *   <li>Failover: 失败自动切换,重试其他服务器(默认)</li>
     *   <li>Failfast: 快速失败,只发起一次调用,失败立即报错</li>
     *   <li>Failsafe: 失败安全,出现异常时忽略</li>
     * </ul>
     * 
     * @return 容错策略枚举
     */
    FaultTolerant faultTolerant() default FaultTolerant.Failover;

    /**
     * 负载均衡策略
     * <p>当服务有多个提供者时,选择调用哪个提供者的策略:
     * <ul>
     *   <li>Round: 轮询,依次调用每个服务器(默认)</li>
     *   <li>Random: 随机选择一个服务器</li>
     *   <li>Hash: 一致性Hash,相同参数总是路由到同一个服务器</li>
     * </ul>
     * 
     * <p><b>注意:</b> 枚举形式仅作为文档参考,实际配置建议使用字符串形式,
     * 这样用户可以扩展自定义的负载均衡策略而不需要修改枚举。
     * 
     * @return 负载均衡策略枚举
     */
    LoadBalance loadBalance() default LoadBalance.Round;

    /**
     * 超时时间值
     * <p>远程调用的超时时间,与timeUnit配合使用。
     * 如果在指定时间内没有收到响应,则认为调用失败。
     * 
     * @return 超时时间值,默认3000
     */
    long time() default 3000;

    /**
     * 超时时间单位
     * <p>与time配合使用,指定超时时间的单位。
     * 
     * @return 时间单位,默认为毫秒
     */
    TimeUnit timeUnit() default TimeUnit.MILLISECONDS;
}
